package com.demo.security.impl;

import java.util.List;

import org.springframework.security.acls.domain.AuditLogger;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.Permission;
import org.springframework.security.acls.model.PermissionGrantingStrategy;
import org.springframework.security.acls.model.Sid;
import org.springframework.util.Assert;

/**
 * 遗传性许可验证策略 策略模型，在Acl创建时，传入此策略。 
 * 判断是否有权限（将Mask和Sid进行比较）
 * 
 * @see link{DefaultPermissionGrantingStrategy}
 * @author ryuu.kk
 * 
 */
public class InheritancePermissionGrantingStrategy implements PermissionGrantingStrategy {
	
	/** 审计日志 **/
	private final transient AuditLogger auditLogger;

	/**
	 * 创建一个审计日志。
	 * @param auditLogger 审计日志
	 */
	public InheritancePermissionGrantingStrategy(AuditLogger auditLogger) {
		Assert.notNull(auditLogger, "auditLogger cannot be null");
		this.auditLogger = auditLogger;
	}

	@Override
	public boolean isGranted(Acl acl, List<Permission> permission,
			List<Sid> sids, boolean administrativeMode) {
		final List<AccessControlEntry> aces = acl.getEntries();

		AccessControlEntry firstRejection = null;
		for (Permission p : permission) {
			for (Sid sid : sids) {
				// 推出loop的标志
				boolean scanNextSid = true;
				for (AccessControlEntry ace : aces) {
					// 遗传性 1>>2>>4>>8>>16
					if (ace.getPermission().getMask() >= p.getMask() && sid.equals(ace.getSid())) {
						//这里的isGranting需要确定
						if (ace.isGranting()) {
							if (!administrativeMode) {
								auditLogger.logIfNeeded(true, ace);
							}
							return true;
						}
                        if (firstRejection == null) {
                            firstRejection = ace;
                        }
                        scanNextSid = false; 
                        break; // exit aces loop
					}
				}
                if (!scanNextSid) {
                    break; // exit SID for loop (now try next permission)
                }
			}
		}
		if (firstRejection != null) {
            // We found an ACE to reject the request at this point, as no
            // other ACEs were found that granted a different permission
            if (!administrativeMode) {
                auditLogger.logIfNeeded(false, firstRejection);
            }
            return false;
        }

        //根据遗传性继续检查
        if (acl.isEntriesInheriting() && (acl.getParentAcl() != null)) {
            // 递归父级方法
            return acl.getParentAcl().isGranted(permission, sids, false);
        } else {
            // We either have no parent, or we're the uppermost parent
            throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs");
        }
	}
}
